/**
/**
 * @class TrackMatte
 * @description 动态扫描雷达类，用于在Cesium地图上创建一个旋转的雷达扫描效果
 * @param {Object} val - 配置参数对象
 * @param {Cesium.Viewer} val.viewer - Cesium Viewer实例
 * @param {String} val.id - 雷达实例唯一标识
 * @param {Array<number>} val.position - 雷达位置的经纬度数组 [经度, 纬度]
 * @param {number} val.shortwaveRange - 雷达扫描半径（米）
 * @example
 * // 创建雷达实例
 * const radar = new TrackMatte({
 *   viewer: cesiumViewer,
 *   id: 'radar1',
 *   position: [116.397428, 39.90923],  // 北京坐标示例
 *   shortwaveRange: 5000  // 5公里半径
 * });
*/
import * as Cesium from 'cesium'
export default class TrackMatte {
    /**
     * 构造函数，初始化雷达扫描实例
     * @param {Object} val - 配置参数对象
     */
    constructor(val) {
        // 初始化成员变量
        this.viewer = val.viewer;          // Cesium Viewer实例
        this.id = val.id;                  // 雷达唯一标识
        this.shortwaveRange = val.shortwaveRange; // 雷达扫描半径
        this.longitude = val.position[0];  // 经度
        this.latitude = val.position[1];   // 纬度
        
        // 从viewer中获取Cesium实例，避免直接使用全局Cesium
        this.Cesium = this.viewer.Cesium || Cesium;
        
        // 将经纬度转换为Cesium笛卡尔坐标
        this.position = this.Cesium.Cartesian3.fromDegrees(
            val.position[0],
            val.position[1],
        );
        
        this.heading = 0;                  // 初始旋转角度为0度
        
        // 计算初始扫描位置点集，用于显示初始状态
        this.positionArr = this.calcPoints(
            val.position[0],
            val.position[1],
            val.shortwaveRange,
            0
        ); // 存储扫描扇区的位置坐标数组
        
        // 添加雷达实体到地图
        this.addEntities();
    }
    
    /**
     * 添加雷达扫描实体到Cesium Viewer
     * 创建两个可视化元素：扫描扇区(扇形墙)和雷达覆盖范围(椭球体)
     */
    addEntities() {
        let entity = this.viewer.entities.add({
            id: this.id,           // 设置实体ID
            position: this.position, // 设置实体位置
            wall: {                 // 雷达扫描扇区（使用墙实体模拟）
                // 使用CallbackProperty动态更新扇区位置
                positions: new this.Cesium.CallbackProperty(() => {
                    // 将经纬度高度数组转换为Cesium笛卡尔坐标
                    return this.Cesium.Cartesian3.fromDegreesArrayHeights(this.positionArr);
                }, false),
                // 设置扇区颜色（青色半透明）
                material: new this.Cesium.Color.fromCssColorString("#00dcff82"),
                // 设置显示距离条件（0到10500公里）
                distanceDisplayCondition: new this.Cesium.DistanceDisplayCondition(
                    0.0,
                    10.5e6
                ),
            },
            ellipsoid: {            // 雷达覆盖范围（使用椭球体模拟）
                // 设置椭球体半径，XYZ方向均为雷达范围
                radii: new this.Cesium.Cartesian3(
                    this.shortwaveRange,
                    this.shortwaveRange,
                    this.shortwaveRange
                ),
                // 设置圆锥角度为90度
                maximumCone: this.Cesium.Math.toRadians(90),
                // 设置填充颜色（青色半透明）
                material: new this.Cesium.Color.fromCssColorString("#00dcff82"),
                // 显示轮廓线
                outline: true,
                // 轮廓线颜色（青色半透明）
                outlineColor: new this.Cesium.Color.fromCssColorString("#00dcff82"),
                // 轮廓线宽度
                outlineWidth: 1,
                // 设置显示距离条件
                distanceDisplayCondition: new this.Cesium.DistanceDisplayCondition(
                    0.0,
                    10.5e6
                ),
            },
        });
        
        // 添加动画更新函数
        this.addPostRender();
    }
    /**
     * 添加雷达扫描动画更新逻辑
     * 通过监听Cesium时钟的onTick事件，实现雷达扫描扇区的旋转动画
     */
    addPostRender() {
        // 注册时钟tick事件监听器，每帧更新一次
        this.viewer.clock.onTick.addEventListener(() => {
            // 增加旋转角度，控制扫描速度（每帧增加10度）
            this.heading += 10.0; // 可调节转动速度
            
            // 根据新的旋转角度重新计算扫描扇区的位置点集
            this.positionArr = this.calcPoints(
                this.longitude,
                this.latitude,
                this.shortwaveRange,
                this.heading
            );
        });
    }
    /**
     * 计算雷达扫描扇区的坐标点集
     * 根据雷达位置、半径和旋转角度计算扫描扇区的边界点坐标
     * 使用东-北-上坐标系和矩阵变换实现准确的坐标计算
     * 
     * @param {number} x1 - 雷达中心点经度
     * @param {number} y1 - 雷达中心点纬度
     * @param {number} radius - 雷达扫描半径（米）
     * @param {number} heading - 雷达旋转角度（度）
     * @returns {Array<number>} 扫描扇区的坐标点集，用于构建可视化效果
     */
    calcPoints(x1, y1, radius, heading) {
        // 计算东-北-上坐标系转换矩阵，以雷达中心为原点
        var m = this.Cesium.Transforms.eastNorthUpToFixedFrame(
            this.Cesium.Cartesian3.fromDegrees(x1, y1)
        );
        
        // 根据旋转角度计算极坐标下的x和y分量
        // 将角度转换为弧度进行三角函数计算
        var rx = radius * Math.cos((heading * Math.PI) / 180.0);
        var ry = radius * Math.sin((heading * Math.PI) / 180.0);
        
        // 创建笛卡尔坐标向量，表示从原点到扫描边缘点的位移
        var translation = this.Cesium.Cartesian3.fromElements(rx, ry, 0);
        
        // 应用坐标变换，将局部坐标转换为世界坐标
        var d = this.Cesium.Matrix4.multiplyByPoint(
            m,
            translation,
            new this.Cesium.Cartesian3()
        );
        
        // 将笛卡尔坐标转换为地理坐标（弧度）
        var c = this.Cesium.Cartographic.fromCartesian(d);
        
        // 将地理坐标转换为度数格式
        var x2 = this.Cesium.Math.toDegrees(c.longitude);
        var y2 = this.Cesium.Math.toDegrees(c.latitude);
        
        // 调用computeCirclularFlight方法计算完整扇区的所有坐标点
        // 0表示起始角度，90表示扇区跨度为90度
        return this.computeCirclularFlight(x1, y1, x2, y2, 0, 90);
    }
    /**
     * 计算圆弧飞行路径的坐标点集
     * 生成从中心点到目标半径点形成的圆弧上的所有点，用于构建雷达扫描扇区
     * 
     * @param {number} x1 - 中心点经度
     * @param {number} y1 - 中心点纬度
     * @param {number} x2 - 半径端点经度（用于计算半径距离和方向）
     * @param {number} y2 - 半径端点纬度（用于计算半径距离和方向）
     * @param {number} fx - 起始角度（度）
     * @param {number} angle - 扫描扇区的角度范围（度）
     * @returns {Array<number>} 圆弧路径的坐标点集，格式为[lon1,lat1,height1,lon2,lat2,height2,...]
     */
    computeCirclularFlight(x1, y1, x2, y2, fx, angle) {
        let positionArr = [];
        
        // 添加中心点（雷达位置）
        positionArr.push(x1);
        positionArr.push(y1);
        positionArr.push(0);
        
        // 计算中心点到目标点的直线距离（米）
        var radius = this.Cesium.Cartesian3.distance(
            this.Cesium.Cartesian3.fromDegrees(x1, y1),
            this.Cesium.Cartesian3.fromDegrees(x2, y2)
        );
        
        // 计算圆弧上的点，根据角度范围生成扇区边界点
        for (let i = fx; i <= fx + angle; i++) {
            // 计算当前角度对应的高度
            let h = radius * Math.sin((i * Math.PI) / 180.0);
            // 计算当前角度对应的水平分量
            let r = Math.cos((i * Math.PI) / 180.0);
            // 计算当前点的经度坐标
            let x = (x2 - x1) * r + x1;
            // 计算当前点的纬度坐标
            let y = (y2 - y1) * r + y1;
            // 添加当前点到结果数组
            positionArr.push(x);
            positionArr.push(y);
            positionArr.push(h);
        }
        
        return positionArr;
    }
}